package com.aliyun.heiyu.powermaster.server.rotary.service.impl;

import com.aliyun.heiyu.common.util.StringUtil;
import com.aliyun.heiyu.powermaster.proto.*;
import com.aliyun.heiyu.powermaster.server.Error;
import com.aliyun.heiyu.powermaster.server.annotation.Transactional;
import com.aliyun.heiyu.powermaster.server.rotary.dao.AlgorithmDAO;
import com.aliyun.heiyu.powermaster.server.rotary.dao.impl.AlgorithmDAOImpl;
import com.aliyun.heiyu.powermaster.server.rotary.exception.AlgorithmExceptionEnum;
import com.aliyun.heiyu.powermaster.server.rotary.exception.CommonExceptionEnum;
import com.aliyun.heiyu.powermaster.server.rotary.object.entity.AlgorithmEntity;
import com.aliyun.heiyu.powermaster.server.rotary.service.AlgorithmService;
import com.aliyun.heiyu.powermaster.server.rotary.task.Task;
import com.aliyun.heiyu.powermaster.server.rotary.utils.UUIDUtil;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @program: heiyu
 * @description: 算法业务实现
 * @author: zhangshun
 * @create: 2020-02-17 11:26
 **/
public class AlgorithmServiceImpl implements AlgorithmService {
    private static Logger logger = LoggerFactory.getLogger(AlgorithmServiceImpl.class);

    private AlgorithmDAO algorithmDAO;
    private Task task;
    public AlgorithmServiceImpl() {
        task = new Task(1);
        algorithmDAO = new AlgorithmDAOImpl();
    }

    /**
     * 算法详情
     *
     * @param request
     * @return
     */
    @Override
    public AlgorithmReply queryAlgorithmById(AlgorithmRequest request) {
        AlgorithmReply.Builder builder = AlgorithmReply.newBuilder();
        if (StringUtil.isEmpty(request.getId())) {
            return builder.setErrCode(CommonExceptionEnum.KEY_EMPTY.getCode())
                .setErrMsg(CommonExceptionEnum.KEY_EMPTY.getMsg()).build();
        }
        //1.查询算法
        AlgorithmEntity algo = algorithmDAO.queryAlgorithmById(request.getId());
        if (null == algo) {
            return builder.setErrCode(Error.FAILED.getCode())
                .setErrMsg(Error.FAILED.getMessage()).build();
        }
        Algorithm.Builder entity = Algorithm.newBuilder();
        entity.setId(algo.getId());
        entity.setAlgoName(algo.getAlgo_name());
        entity.setCoolingAllowance(algo.getCooling_allowance());
        entity.setControlFrequency(algo.getControl_frequency());
        entity.setTempPrecision(algo.getTemp_precision());
        entity.setAlgoSwitch(algo.getAlgo_switch());
        return builder.setErrCode(Error.SUCCESS.getCode())
            .setErrMsg(Error.SUCCESS.getMessage())
            .setData(entity).build();
    }

    /**
     * 查询算法列表
     *
     * @param request
     * @return
     */
    @Override
    public AlgorithmsReply queryAlgorithms(AlgorithmsRequest request) {
        AlgorithmsReply.Builder builder = AlgorithmsReply.newBuilder();
        List<AlgorithmEntity> list = algorithmDAO.queryAlgorithms(request);
        if (CollectionUtils.isEmpty(list)) {
            return builder.setErrCode(Error.SUCCESS.getCode())
                .setErrMsg(Error.SUCCESS.getMessage())
                .build();
        }
        for (AlgorithmEntity algo : list) {
            Algorithm.Builder entity = Algorithm.newBuilder();
            entity.setId(algo.getId());
            entity.setAlgoName(algo.getAlgo_name());
            entity.setCoolingAllowance(algo.getCooling_allowance());
            entity.setControlFrequency(algo.getControl_frequency());
            entity.setTempPrecision(algo.getTemp_precision());
            entity.setAlgoSwitch(algo.getAlgo_switch());
            builder.addData(entity);
        }
        return builder.setErrCode(Error.SUCCESS.getCode())
            .setErrMsg(Error.SUCCESS.getMessage())
            .build();
    }

    /**
     * 删除算法
     *
     * @param request
     * @return
     */
    @Override
    @Transactional
    public CommonReply deleteAlgorithm(AlgorithmRequest request) {
        CommonReply.Builder builder = CommonReply.newBuilder();
        if (StringUtil.isEmpty(request.getId())) {
            return builder.setErrCode(CommonExceptionEnum.KEY_EMPTY.getCode())
                .setErrMsg(CommonExceptionEnum.KEY_EMPTY.getMsg()).build();
        }
        //1.查询策略是否在使用
        AlgorithmEntity entity = algorithmDAO.queryAlgorithmById(request.getId());
        if(null == entity){
            return builder.setErrCode(AlgorithmExceptionEnum.ALGO_NOT_EXIST.getCode())
                .setErrMsg(AlgorithmExceptionEnum.ALGO_NOT_EXIST.getMsg())
                .build();
        }
        if (entity.getAlgo_switch() == 1 ) {
            return builder.setErrCode(AlgorithmExceptionEnum.ALGO_USED.getCode())
                .setErrMsg(AlgorithmExceptionEnum.ALGO_USED.getMsg())
                .build();
        }
        //2.删除算法
        boolean algorithm = algorithmDAO.deleteAlgorithm(request.getId());
        if (algorithm) {
            return builder.setErrCode(Error.SUCCESS.getCode())
                .setErrMsg(Error.SUCCESS.getMessage())
                .build();
        }
        return builder.setErrCode(Error.FAILED.getCode())
            .setErrMsg(Error.FAILED.getMessage())
            .build();
    }
    /**
     * 添加算法
     *
     * @param request
     * @return
     */
    @Override
    @Transactional
    public CommonReply addAlgorithm(AlgorithmRequest request) {
        AlgorithmRequest.Builder req = request.toBuilder();
        CommonReply.Builder builder = CommonReply.newBuilder();
        //1.算法名称不能为空
        if (StringUtil.isEmpty(req.getAlgoName())) {
            return builder.setErrCode(AlgorithmExceptionEnum.ALGO_EMPTY.getCode())
                .setErrMsg(AlgorithmExceptionEnum.ALGO_EMPTY.getMsg())
                .build();
        }
        //2.算法名称是否存在
        AlgorithmEntity algorithmEntity = algorithmDAO.queryAlgoByName(req.getAlgoName());
        if (null != algorithmEntity) {
            return builder.setErrCode(AlgorithmExceptionEnum.ALGO_NAME_EXIST.getCode())
                .setErrMsg(AlgorithmExceptionEnum.ALGO_NAME_EXIST.getMsg())
                .build();
        }
        //3.添加算法
        String uuid = UUIDUtil.getUUID();
        req.setId(uuid);
        algorithmDAO.addAlgorithm(req.build());
        return builder.setErrCode(Error.SUCCESS.getCode())
            .setErrMsg(Error.SUCCESS.getMessage())
            .build();
    }

    /**
     * 修改算法
     *
     * @param request
     * @return
     */
    @Override
    @Transactional
    public CommonReply updateAlgorithm(AlgorithmRequest request) {
        CommonReply.Builder builder = CommonReply.newBuilder();
        //1.判断主键是否为空
        if (StringUtil.isEmpty(request.getId())) {
            return builder.setErrCode(CommonExceptionEnum.KEY_EMPTY.getCode())
                .setErrMsg(CommonExceptionEnum.KEY_EMPTY.getMsg()).build();
        }
        //2.修改算法
        boolean algorithm = algorithmDAO.updateAlgorithm(request);
        logger.info("制冷策略修改算法:{}",algorithm);
        if (!algorithm) {
            changeTemJob();
            return builder.setErrCode(Error.FAILED.getCode())
                .setErrMsg(Error.FAILED.getMessage())
                .build();
        }
        return builder.setErrCode(Error.SUCCESS.getCode())
            .setErrMsg(Error.SUCCESS.getMessage())
            .build();
    }

    /**
     * 算法开关
     *
     * @param request
     * @return
     */
    @Override
    @Transactional
    public CommonReply updateAlgorithmSwitch(AlgorithmRequest request) {
        CommonReply.Builder builder = CommonReply.newBuilder();
        //1.判断主键是否为空
        if (StringUtil.isEmpty(request.getId())) {
            return builder.setErrCode(CommonExceptionEnum.KEY_EMPTY.getCode())
                .setErrMsg(CommonExceptionEnum.KEY_EMPTY.getMsg()).build();
        }
        //2.不能关闭算法
        if (request.getAlgoSwitch() == 0) {
            return builder.setErrCode(AlgorithmExceptionEnum.ALGO_NOT_CLOSE.getCode())
                .setErrMsg(AlgorithmExceptionEnum.ALGO_NOT_CLOSE.getMsg())
                .build();
        }
        //3.查询在使用的制冷策略
        AlgorithmEntity entity = algorithmDAO.queryAlgorithmById(request.getId());
        //4.判断算法是否在使用
        if(entity.getAlgo_switch() == 1){
            return builder.setErrCode(AlgorithmExceptionEnum.ALGO_USED.getCode())
                .setErrMsg(AlgorithmExceptionEnum.ALGO_USED.getMsg())
                .build();
        }
        //5.关闭所有策略
        boolean algos = algorithmDAO.closeAlgos();

        //6.切换算法
        boolean aSwitch = false;
        if(algos){
            aSwitch = algorithmDAO.updateAlgorithmSwitch(request);
        }
        logger.info("制冷策略切换算法:{}",aSwitch);
        //6.判断是否切换成功
        if (aSwitch) {
            changeTemJob();
            return builder.setErrCode(Error.SUCCESS.getCode())
                .setErrMsg(Error.SUCCESS.getMessage())
                .build();
            //7.判断是否重启定时器
        }
        return builder.setErrCode(Error.FAILED.getCode())
            .setErrMsg(Error.FAILED.getMessage())
            .build();
    }

    /**
     * 重启预测空调温度定时器
     */
    public void changeTemJob() {
        logger.info("重启制冷策略空调温度定时器changeTemJob");
        AlgorithmEntity algoUse = algorithmDAO.queryAlgoUse();
        AlgorithmEntity old = Task.algo;
        if (algoUse != null) {
            Task.algo = algoUse;
        }
        logger.info("使用的制冷策略实体:{}  查詢到的制冷策略:{}", old,algoUse);
        if (null != old && null != algoUse) {
            if (algoUse.getControl_frequency() != old.getControl_frequency()) {
                logger.info("执行制冷策略重启计划");
                task.reStartModel();
            }
        }
    }
}
